using Com.Ctrip.Framework.Apollo;
using Consul;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Primitives;
using Repository.communal;
using Serilog;
using Serilog.Events;
using Serilog.Sinks.Elasticsearch;
using SqlSugar;
using System.Reflection;
using Warehouse.Repository;

/// <summary>
/// 应用程序入口点 - 配置和启动 ASP.NET Core 应用程序
/// 实现实时数据推送、API 服务、数据库访问等功能
/// </summary>
var builder = WebApplication.CreateBuilder(args);

// ==================== 服务注册阶段 ====================

// 注册控制器服务 - 启用 MVC 控制器功能
builder.Services.AddControllers();

// 注册 API 文档服务 - 启用 Swagger/OpenAPI 文档生成
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

// 注册 Entity Framework Core 数据库上下文
// 配置 MySQL 数据库连接，支持实体框架的 ORM 功能
builder.Services.AddDbContext<MyDbContext>(options =>
    options.UseMySql(
        builder.Configuration.GetValue<string>("warehouse"), // 从配置文件读取连接字符串
        new MySqlServerVersion(new Version(9, 4)) // 指定 MySQL 服务器版本
    )
);
//Program中 
var configuration = builder.Configuration;
// 配置Serilog
var elaUri = configuration["ELK:ElaticSearchUrl"];
var userName = configuration["ELK:UserName"];
var password = configuration["ELK:Password"];
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information()
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.Enrich.FromLogContext()
.Enrich.WithMachineName()
.Enrich.WithThreadId()
.Enrich.WithProcessId()
.WriteTo.Console(new Serilog.Formatting.Compact.CompactJsonFormatter())
.WriteTo.File("logs/warehouseapiread-.txt",
rollingInterval: RollingInterval.Day,
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}")
.WriteTo.Elasticsearch(new ElasticsearchSinkOptions(new Uri(elaUri))
{
    IndexFormat = "warehouseapiread-logs-{0:yyyy.MM.dd}",
    AutoRegisterTemplate = true,
    AutoRegisterTemplateVersion = AutoRegisterTemplateVersion.ESv7,
    ModifyConnectionSettings = conn => conn.BasicAuthentication(userName, password),
    BufferBaseFilename = "./logs/serilog-buffer",
    Period = TimeSpan.FromSeconds(2)
})
.CreateLogger();
builder.Host.UseSerilog();
// 注册 SqlSugar 数据库客户端 - 轻量级 ORM 框架
// 提供高性能的数据库访问和查询功能
builder.Services.AddScoped<ISqlSugarClient>(provider =>
{
    // 从配置中获取数据库连接字符串
    var connectionString = builder.Configuration.GetValue<string>("warehouse");

    // 创建 SqlSugar 客户端实例
    return new SqlSugarClient(new ConnectionConfig()
    {
        ConnectionString = connectionString,    // 数据库连接字符串
        DbType = DbType.MySql,                 // 数据库类型：MySQL
        IsAutoCloseConnection = true,          // 自动关闭连接，提高性能
        InitKeyType = InitKeyType.Attribute    // 使用特性初始化主键
    });
});
static void RegisterConsul()
{
    try
    {
        var consulClient = new ConsulClient(p => {
            p.Address = new Uri("http://115.190.167.248:8500");//主机ip:8500
        });
        // 2. 确保健康检查端点可访问
        var httpCheck = new AgentServiceCheck()
        {
            DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),
            Interval = TimeSpan.FromSeconds(10),
            HTTP = "http://114.132.166.218:7011/WeatherForecast", // 确认此端口服务是否运行,WeatherForecast是天气预报控制器，如果没有这个控制器可以手动创建一个
            Timeout = TimeSpan.FromSeconds(5)
        };
        // 3. 添加标签方便识别
        var registration = new AgentServiceRegistration()
        {
            Checks = new[] { httpCheck },
            ID = $"warehouseread-{Guid.NewGuid()}", // 更易读的ID
            Name = "warehouseread",                // 业务api名称,必须小写
            Address = "115.190.167.248",                   // 纯IP正确
            Port = 7011,                               // 端口与健康检查一致
            Tags = new[] { "dotnet-service" }           // 添加标签
        };

        // 4. 添加错误处理
        var result = consulClient.Agent.ServiceRegister(registration).Result;
        Console.WriteLine($"服务注册成功! Status: {result.StatusCode}");
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Consul注册失败: {ex.Message}");
    }
}
// 注册 MediatR 中介者模式 - 实现 CQRS 模式
// 自动扫描当前程序集中的所有请求处理器
builder.Services.AddMediatR(cfg => {
    cfg.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly());
});
builder.Configuration.AddApollo(builder.Configuration.GetSection("Apollo")).AddDefault().AddNamespace("systemread");
// 注册 SignalR 服务 - 启用实时通信功能
// 支持 WebSocket 和 Long Polling 传输协议
builder.Services.AddSignalR(options =>
{
    // 配置连接超时时间（30秒）
    options.ClientTimeoutInterval = TimeSpan.FromSeconds(30);
    // 配置握手超时时间（15秒）
    options.HandshakeTimeout = TimeSpan.FromSeconds(15);
    // 配置保持连接间隔（15秒）
    options.KeepAliveInterval = TimeSpan.FromSeconds(15);
});

// 注册业务服务 - 实现依赖注入
// CommonService 负责处理 SignalR Hub 的业务逻辑
builder.Services.AddScoped<Warehouse.API.Read.HubService.CommonService>();

// 注册调拨单相关服务
builder.Services.AddScoped<IAllocationRepository, AllocationRepository>();
builder.Services.AddScoped<Warehouse.Services.IServices.IAllocationService, Warehouse.Services.Services.AllocationService>();

// 配置 CORS（跨域资源共享）策略
// 解决前端应用与后端 API 的跨域访问问题
builder.Services.AddCors(options =>
{
    options.AddPolicy("AllowFrontend", policy =>
    {
        // 允许的前端应用地址
        policy.WithOrigins(
            "http://localhost:5173"  // Vue 3 开发服务器默认端口
        )
        .AllowCredentials()  // 允许携带认证信息（Cookie、Authorization 头等）
        .AllowAnyHeader()    // 允许任何请求头
        .AllowAnyMethod();   // 允许任何 HTTP 方法（GET、POST、PUT、DELETE 等）
    });
});

// ==================== 应用程序构建阶段 ====================
var app = builder.Build();

// ==================== 中间件管道配置阶段 ====================

if (app.Configuration is IConfigurationRoot configurationRoot)
{
    ChangeToken.OnChange(
        () => configurationRoot.GetReloadToken(),
        () => Console.WriteLine($"配置已更新:{app.Configuration.GetValue<string>("warehouse")}"));
}
RegisterConsul();
// 启用 Swagger 文档中间件
// 提供 API 文档的 HTTP 端点
app.UseSwagger();

// 启用 Swagger UI 中间件
// 提供可视化的 API 文档界面
app.UseSwaggerUI();

// 启用 CORS 中间件
// 处理跨域请求，必须在路由中间件之前
app.UseCors("AllowFrontend");

// 启用授权中间件
// 处理身份验证和授权逻辑
app.UseAuthorization();

// 映射控制器路由
// 启用 MVC 控制器的路由功能
app.MapControllers();

// 映射 SignalR Hub 路由
// 建立实时通信端点：/chathub
// 客户端通过此端点建立 WebSocket 连接
app.MapHub<Warehouse.API.Read.Hubs.ChatHub>("/chathub");

// ==================== 应用程序启动 ====================
// 启动 Web 服务器，开始监听 HTTP 请求
app.Run();
